//Documentation complete
/**
 * @author Alex
 * @version 2009AP06
 */

package control;

import broker.*;
import problemDomain.*;
import static problemDomain.ErrorBean.*;
import static problemDomain.ErrorBean.ErrorCode.*;

import java.awt.*;
import java.awt.geom.Point2D;
import java.util.Date;

import org.jCharts.axisChart.ScatterPlotAxisChart;
import org.jCharts.chartData.*;
import org.jCharts.properties.*;
import org.jCharts.properties.util.ChartFont;

/**
 * Control object for popularity vs. productivity report.
 */
public class ProductivityPopularityReportControl extends Control {
	
	/* Attributes */
	
	private ProductivityPopularityReportBroker pprb;
	
	/* END Attributes */
	
	
	/* Constructors*/
	
	/**
	 * Constructs a <code>ProductivityPopularityReportControl</code>.
	 * @throws ErrorBean it the database is not available
	 */
	public ProductivityPopularityReportControl () throws ErrorBean {
		pprb = ProductivityPopularityReportBroker.getBroker();
	}
	
	/* END Constructors*/
	
	
	/* Methods */
	
	/**
	 * Generates the report.
	 * @param from the date to lower bound the report
	 * @param to the date to upper bound the report
	 * @return the chart generated for the report
	 * @throws ErrorBean if the input data are not correct
	 */
	public ScatterPlotAxisChart report (Date from, Date to) throws ErrorBean {
		try {
			Stroke [] strokes = new Stroke [] {new Stroke() {
				@Override
				public Shape createStrokedShape (Shape p) {
					return p;
				}
			}};
			Shape [] shapes = new Shape [] {PointChartProperties.SHAPE_DIAMOND};
			
			ScatterPlotDataSet scatterPlotDataSet = new ScatterPlotDataSet(new ScatterPlotProperties(strokes, shapes));
			
			Point2D.Double [] points = pprb.getDataPoints(from, to);
			Bounds bounds = getBounds(points);
			
			scatterPlotDataSet.addDataPoints(points, Color.RED, "Proprietary");
			
			ScatterPlotDataSeries scatterPlotDataSeries = new ScatterPlotDataSeries(
				scatterPlotDataSet, "Popularity", "Profitability", "Popularity vs. Profitability");
			
			ChartFont titleFont = new ChartFont(
				new Font("Georgia Negreta cursiva", Font.PLAIN, 14), Color.BLACK);
			ChartFont axisTitleFont = new ChartFont(
				new Font("Arial Narrow", Font.PLAIN, 14), Color.BLACK);
			ChartFont axisScaleFont = new ChartFont(
				new Font("Georgia Negreta cursiva", Font.PLAIN, 13), Color.BLACK);
			
			DataAxisProperties xAxisProperties = new DataAxisProperties();
			xAxisProperties.setUserDefinedScale(bounds.xMin, 1);
			xAxisProperties.setNumItems(points.length);
			xAxisProperties.setScaleChartFont(axisScaleFont);
			xAxisProperties.setTitleChartFont(axisTitleFont);
			//xAxisProperties.setNumItems(10);
			//xAxisProperties.setRoundToNearest(0);
	
			DataAxisProperties yAxisProperties = new DataAxisProperties();
			yAxisProperties.setUserDefinedScale(bounds.yMin, 0.2);
			yAxisProperties.setNumItems(points.length);
			yAxisProperties.setScaleChartFont(axisScaleFont);
			yAxisProperties.setTitleChartFont(axisTitleFont);
			//yAxisProperties.setNumItems(10);
			//yAxisProperties.setRoundToNearest(1);
			
			AxisProperties axisProperties = new AxisProperties(
				xAxisProperties, yAxisProperties);
			
			ChartProperties chartProperties = new ChartProperties();
			chartProperties.setTitleFont(titleFont);
			
			LegendProperties legendProperties = new LegendProperties();
	
			return new ScatterPlotAxisChart(
				scatterPlotDataSeries, chartProperties, axisProperties,
				legendProperties, 550, 360);
		} catch (PropertyException e) {
			throwError(
				REPORT_CANNOT_GENERATE_CHART,
				e.getMessage(),
				this);
			return null;
		}
	}
	
	/* END Methods */
	
	
	/* Local Methods */
	
	private Bounds getBounds (Point2D.Double [] points) {
		double xMin = Double.MAX_VALUE;
		double xMax = Double.MIN_VALUE;
		double yMin = Double.MAX_VALUE;
		double yMax = Double.MIN_VALUE;
		for (int i = 0; i < points.length; i++) {
			xMin = (points[i].x < xMin ? points[i].x : xMin);
			xMax = (points[i].x > xMax ? points[i].x : xMax);
			yMin = (points[i].y < yMin ? points[i].y : yMin);
			yMax = (points[i].y > yMax ? points[i].y : yMax);
		}
		return new Bounds(xMin, xMax, yMin, yMax);
	}
	
	/* Local Methods */
	
	
	/* (Bounds) Class */
	
	private class Bounds {
		
		public double xMin;
		public double xMax;
		public double yMin;
		public double yMax;
		
		public Bounds (double xMin, double xMax, double yMin, double yMax) {
			this.xMin = xMin;
			this.xMax = xMax;
			this.yMin = yMin;
			this.yMax = yMax;
		}
		
		@Override
		public String toString () {
			return "xMin: " + xMin + ", xMax: " + xMax + ", yMin: " + yMin + ", yMax: " + yMax; 
		}
		
	}
	
	/* END (Bounds) Class */
	
}
